JavaScript 事件模型系列(三)事件对象

定义

在触发事件时,会产生一个事件对象 event,这个对象包含着所有与事件有关的信息,例如一个鼠标点击事件对象就包括鼠标的位置信息,事件的类型,触发事件的元素等信息。

具体事件对象

具体看一个键盘键入事件对象的所有属性:

键盘输入事件对象

一个事件对象根据事件类型的有很多很多属性,然而我们关注的对象属性是事件类型、事件目标、阻止事件冒泡、阻止事件默认行为等。

事件对象的重点属性和方法

事件的目标

这一属性表示事件的实际目标,比如我们点击一个按钮,target 返回整个按钮标签。注在 IE 浏览器中表示事件的目标的属性是 srcElement。

1
2
3
4
5
6
7
<button id="btn">Click Me</button>
var btn = document.getElementById("btn");
btn.addEventListener("click",function(event) {
console.log(event.target); // <button id="btn">Click Me</button>
},false);

在非 IE 浏览器中的事件对象中,还有一个 currentTarget 属性,在事件处理程序内部,this 始终等于 currentTarget 的值,表示事件处理程序当前正在处理事件的那个元素。比如在下面的列表中:

1
2
3
4
5
<ul id="uList">
<li id="list1">List one</li>
<li id="list2">List Two</li>
<li id="list3">List Three</li>
</ul>

如果我们将事件处理程序绑定到 li 中,点击 li,this,target,currentTatget 三者均表示该 li。

1
2
3
4
5
6
7
var list1 = document.getElementById("list1");
list1.addEventListener("click",function(event) {
console.log(event.target); // <li id="list1">List one</li>
console.log(event.currentTarget); // <li id="list1">List one</li>
console.log(event.target == event.currentTarget); // true
console.log(event.currentTarget == this); // true
},false);

如果将事件处理程序绑定到 ul 中,点击 li,this 和 currentTarget 表示 ul,target 表示 li。

1
2
3
4
5
6
7
var uList = document.getElementById("uList");
uList.addEventListener("click",function(event) {
console.log(event.target); // <li id="list1">List one</li>
console.log(event.currentTarget); // <ul id="uList">...</ul>
console.log(event.target == event.currentTarget); // false
console.log(event.currentTarget == this); // true
},false);

事件类型

event.type 没什么好说的,就是获取触发元素的事件类型。

取消事件的进一步捕获或冒泡

DOM 事件流:

stopPropagation():取消事件的进一步捕获或冒泡,如果 bubbles(表示事件是否冒泡)属性为 true 可以使用这个方法。

stopImmediatePropagation():取消事件进一步捕获或冒泡,同时阻止任何事件处理程序被调用。

IE 事件流:

cancelBubble,默认值为 false,设置为 true 取消事件冒泡,与 stopPropagation() 作用相同。

stopPropagation() 的使用,有一个前提,就是 bubbles 属性为 true。并且 stopPropagation() 除了阻止事件的冒泡还阻止了事件的捕获,就是说阻止了事件的进一步传播。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<div id="superDiv" name="superDiv" value="hello">
<div id="subDiv"></div>
</div>
superDiv.addEventListener("click",function(event) {
console.log("superDiv 捕获模式");
event.stopPropagation();
},true);
superDiv.addEventListener("click",function() {
console.log("superDiv 冒泡模式");
},false);
subDiv.addEventListener("click",function() {
console.log("subDiv 捕获模式");
},true);
subDiv.addEventListener("click",function() {
console.log("subDiv 冒泡模式");
},false);
// superDiv 捕获模式

点击 subDiv,输出结果只有捕获模式下的 superDiv,后续的事件捕获和冒泡都被阻止了。

发现一个问题就是,元素不管是在捕获还是冒泡模式下,都可以使用 stopPropagation(),然后打印出捕获模式下的事件对象的 bubbles 属性发现是 true。个人认为,不管是在捕获还是冒泡模式下,bubbles 的值除非设置为 false,默认值都是 true。

与 stopPropagation() 不同的是,stopPropagation() 可以阻止事件进一步传播,但是不能阻止该元素上绑定的其他函数的执行。比如我们在元素绑定了函数 1 和函数 2,我们在函数 1 上使用了stopPropagation(),那函数 2 还是会执行,但用 stopImmediatePropagation() 就不会了,它会阻止元素上绑定的所有事件处理函数执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
superDiv.addEventListener("click",function(event) {
console.log("superDiv 捕获模式-函数1");
event.stopPropagation();
},true);
superDiv.addEventListener("click",function() {
console.log("superDiv 捕获模式-函数2");
},true);
subDiv.addEventListener("click",function() {
console.log("subDiv 捕获模式");
},true);
// superDiv 捕获模式-函数1
// superDiv 捕获模式-函数2

使用 event.stopPropagation() 方法,会阻止事件进一步冒泡或捕获,不会阻止该元素上绑定的其他函数的执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
superDiv.addEventListener("click",function(event) {
console.log("superDiv 捕获模式-函数1");
event.stopImmediatePropagation();
},true);
superDiv.addEventListener("click",function() {
console.log("superDiv 捕获模式-函数2");
},true);
subDiv.addEventListener("click",function() {
console.log("subDiv 捕获模式");
},true);
// superDiv 捕获模式-函数1

使用 event.stopImmediatePropagation() 不但会阻止事件的进一步冒泡或捕获,也会阻止该元素上绑定的其他函数执行。

在 IE 事件流中,cancelBubble属性 的作用与 stopPropagation() 方法相同。

1
event.cancelBubble = true; // 阻止进一步冒泡

取消事件的默认行为

在使用 JavaScript 编程时会遇到一个问题,就是当你给html添加事件时,由于浏览器默认的事件触发机制,可能会触发你不想触发的行为,例如,当点击提交按钮时会对表单进行提交,点击链接时会跳转到指定页面。

在 DOM 事件流中,调用事件对象的 preventDefault() 方法,在 IE 事件流中,设置事件对象的 returnValue 属性值为 false。

1
2
3
DOM:preventDefault()
IE:returnValue = false
Fork me on GitHub